package com.itheima.reggie.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.reggie.common.R;
import com.itheima.reggie.common.dto.CategoryDto;
import com.itheima.reggie.common.dto.DishListDto;
import com.itheima.reggie.common.dto.DishUpdateDto;
import com.itheima.reggie.entity.*;
import com.itheima.reggie.mapper.DishMapper;
import com.itheima.reggie.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
@Slf4j
public class DishServiceImpl extends ServiceImpl<DishMapper, Dish> implements DishService {
    @Override
    public Integer selectByCategoryId(Long id) {
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Dish::getCategoryId, id);
        List<Dish> list = this.list(wrapper);
        return list.size();
    }


    @Autowired
    DishFlavorService dishFlavorService;

    @Autowired
    CategoryService categoryService;


    @Autowired
    SetmealDishService setmealDishService;

    @Autowired
    SetmealService setmealService;

    @Autowired
    ShoppingCartService shoppingCartService;

    @Value("${dish.path}")
    private String path;

    @Override
    public R<String> dish(CategoryDto categoryDto) {
        /*ModelMapper modelMapper = new ModelMapper();
        CategoryDto categoryDto1 = new CategoryDto();
        Dish map = modelMapper.map(categoryDto1, Dish.class);*/
        if (ObjectUtils.isEmpty(categoryDto)) {
            return R.error("数据异常！");
        }
       /* String image = categoryDto.getImage();

        FileInputStream inpit = null;
        OutputStream output = null;
        try {
            inpit = new FileInputStream(path + image);
            output = new FileOutputStream(path + "saveImg\\" + image);
            IOUtils.copy(inpit, output);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inpit.close();
                output.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }*/

        Dish dish = new Dish();
        BeanUtils.copyProperties(categoryDto, dish);
        /*dish.setImage("saveImg\\\\" + image);*/
        this.save(dish);
        Long id = dish.getId();
        List<DishFlavor> flavors = categoryDto.getFlavors();
        for (DishFlavor flavor : flavors) {
            flavor.setDishId(id);
        }
        dishFlavorService.saveBatch(flavors);
        return R.success("保存成功！");
    }

    @Override
    public R<Page<DishListDto>> findDishPage(Long page, Long pageSize, String name) {
        if (ObjectUtils.isEmpty(page)
                || page <= 0) {
            page = 1L;
        }
        if (ObjectUtils.isEmpty(pageSize)
                || pageSize <= 0) {
            page = 10L;
        }

        Page<Dish> pageParam = new Page<>(page, pageSize);
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(!ObjectUtils.isEmpty(name), Dish::getName, name);
        wrapper.orderByDesc(Dish::getUpdateTime);
        Page<Dish> resultPage = this.page(pageParam, wrapper);
        List<Dish> records = resultPage.getRecords();
        List<DishListDto> listDto = new ArrayList<>();
        for (Dish record : records) {
            Long categoryId = record.getCategoryId();
            Category category = categoryService.getById(categoryId);
            String name1 = category.getName();
            DishListDto dishListDto = new DishListDto();
            BeanUtils.copyProperties(record, dishListDto);
            dishListDto.setCategoryName(name1);
            listDto.add(dishListDto);
        }

        Page<DishListDto> resultPage1 = new Page<>();
        BeanUtils.copyProperties(resultPage, resultPage1);
        resultPage1.setRecords(listDto);
        return R.success(resultPage1);
    }

    @Override
    public R<DishUpdateDto> findDishById(Long id) {

        if (ObjectUtils.isEmpty(id)) {
            return R.error("参数错误！");
        }
        Dish dbDish = this.getById(id);
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DishFlavor::getDishId, id);
        List<DishFlavor> list = dishFlavorService.list(wrapper);

        DishUpdateDto dto = new DishUpdateDto();
        BeanUtils.copyProperties(dbDish, dto);
        dto.setFlavors(list);


        return R.success(dto);
    }

    @Override
    @Transactional
    public R<String> updateDish(DishUpdateDto dishUpdateDto) {
        //1.参数校验
        //略

        //2.逻辑处理
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishUpdateDto, dish);
        this.saveOrUpdate(dish);


        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DishFlavor::getDishId, dishUpdateDto.getId());
        dishFlavorService.remove(wrapper);

        List<DishFlavor> flavors = dishUpdateDto.getFlavors();

        for (DishFlavor flavor : flavors) {
            flavor.setDishId(dishUpdateDto.getId());
        }

        dishFlavorService.saveBatch(flavors);

        //3.数据返回
        return R.success("成功！");
    }

    @Override
    public R<List<DishUpdateDto>> findDishByCategoryId(Long categoryId, Integer status) {

        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(!ObjectUtils.isEmpty(categoryId), Dish::getCategoryId, categoryId);
        wrapper.eq(!ObjectUtils.isEmpty(status), Dish::getStatus, status);
        List<Dish> list = this.list(wrapper);
        ArrayList<DishUpdateDto> dishUpdateDtos = new ArrayList<>();
        for (Dish dish : list) {
            DishUpdateDto dishUpdateDto = new DishUpdateDto();
            LambdaQueryWrapper<DishFlavor> wrapper1 = new LambdaQueryWrapper<>();
            wrapper1.eq(DishFlavor::getDishId, dish.getId());
            List<DishFlavor> list1 = dishFlavorService.list(wrapper1);
            BeanUtils.copyProperties(dish, dishUpdateDto);
            dishUpdateDto.setFlavors(list1);
            dishUpdateDtos.add(dishUpdateDto);
        }
        return R.success(dishUpdateDtos);
    }

    /**
     * 菜品批量删除
     *
     * @param ids
     * @return
     */


    @Override
    public R<String> deleteById(List<Long> ids) {
        //参数校验
        if (ObjectUtils.isEmpty(ids)) {
            return R.error("参数错误！");
        }
        //通过菜品Id遍历套餐数据库，如果套餐数据库有的菜品，不可以删除，没有的放入新集合
        ArrayList<Long> longs = new ArrayList<>();
        for (Long id : ids) {
            SetmealDish byId = setmealDishService.getById(id);
            if (ObjectUtils.isEmpty(byId)) {
                longs.add(id);
            }
        }
        //如果存储可删除菜品Id的新集合长度的等于0，说明所有菜品你均在套餐内，所有菜品均无法删除
        if (longs.size() == 0) {
            return R.error("所有菜品均在套餐内，请先处理套餐！");
        }
        //通过可删除的菜品Id集合去菜品数据库取出所有菜品对象
        LambdaQueryWrapper<Dish> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.in(Dish::getId, longs);
        List<Dish> dishList = this.list(wrapper1);
        //遍历可删除的菜品对象集合，status等于0（说明菜品为停售状态，可删除）的菜品存入新的菜品集合
        ArrayList<Long> dishes = new ArrayList<>();
        for (Dish dish : dishList) {
            Integer status = dish.getStatus();
            if (status == 0) {
                dishes.add(dish.getId());
            }
        }
        //如果集合为空，说明菜品全部为起售状态，无可删的菜品
        if (ObjectUtils.isEmpty(dishes)) {
            return R.error("菜品全部在套餐内或者为在售状态，无法删除！");
        }
        //集合不为空，批量删除菜品
        this.removeByIds(dishes);
        //口味数据库内也要把删除的菜品对应的口味删除
        LambdaQueryWrapper<DishFlavor> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.in(DishFlavor::getDishId, dishes);
        dishFlavorService.remove(wrapper2);
        //返回数据
        return R.success("禁售状态菜品删除成功，起售状态和套餐内产品无法删除！");
    }


    /**
     * 菜品批量停售，菜品包含在套餐内的无法停售
     *
     * @param ids
     * @return
     */
    @Override
    public R<String> stopSell(List<Long> ids) {
        //参数校验
        if (ObjectUtils.isEmpty(ids)) {
            return R.error("参数非法！");
        }
        //想要停售的ids查询套餐内容的库
        LambdaQueryWrapper<SetmealDish> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(SetmealDish::getDishId, ids);
        List<SetmealDish> setmealDishList = setmealDishService.list(wrapper);
        //如果查询结果为null，说明没有任何套餐包含这些菜品，可直接停售
        if (setmealDishList.size() == 0) {
            this.stop(ids);
            return R.success("停售成功！");
        }
        //将套餐内容集合中套餐的Id取出放入set集合
        Set<Long> setmealIds = setmealDishList.stream().map(SetmealDish::getSetmealId).collect(Collectors.toSet());
        //通过set内的Ids查询套餐
        LambdaQueryWrapper<Setmeal> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.in(Setmeal::getId, setmealIds);
        List<Setmeal> setmealList = setmealService.list(wrapper1);
        //遍历套餐集合，在售状态的套餐Id保存
        ArrayList<Long> longs = new ArrayList<>();
        for (Setmeal setmeal : setmealList) {
            if (setmeal.getStatus() == 1) {
                longs.add(setmeal.getId());
            }
        }
        //如果没有在售状态的套餐，所有菜品可直接停售
        if (longs.size() == 0) {
            this.stop(ids);
            return R.success("停售成功！");
        }
        //遍历在售套餐Id集合，通过在售套餐Id查询
        LambdaQueryWrapper<SetmealDish> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.in(SetmealDish::getSetmealId, longs);
        List<SetmealDish> list = setmealDishService.list(wrapper2);
        Set<Long> dishId = list.stream().map(SetmealDish::getDishId).collect(Collectors.toSet());
        ids.removeAll(dishId);
        /*HashSet<Long> longs = new HashSet<>();
        for (SetmealDish setmealDish : setmealDishList) {
            longs.add((setmealDish.getDishId()));
        }
        if (longs.size() == ids.size()) {
            return R.error("菜品全部在套餐内，无法停售！");
        }*/
        //如果ids除去在售套餐包含的id后无id可操作，返回失败
        if (ids.size() == 0) {
            return R.error("失败！");
        }
        //将在售套餐包含的菜品Id去除后，其余菜品停售
        this.stop(ids);
        return R.success("成功！");

    }

    public void stop(List<Long> ids) {
        ArrayList<Dish> dishes = new ArrayList<>();
        for (Long id : ids) {
            Dish dish = new Dish();
            dish.setId(id);
            dish.setStatus(0);
            dishes.add(dish);
        }

        this.updateBatchById(dishes);

    }

    //菜品批量起售

    @Override
    public R<String> startSell(List<Long> ids) {
        if (ObjectUtils.isEmpty(ids)) {
            return R.error("参数非法！");
        }
        ArrayList<Dish> dishes = new ArrayList<>();
        for (Long id : ids) {
            Dish dish = new Dish();
            dish.setId(id);
            dish.setStatus(1);
            dishes.add(dish);
        }

        this.updateBatchById(dishes);
        return R.success("起售成功！");
    }


}